package com.gxtbindings.showcase.client.demo;

import java.util.Arrays;
import java.util.List;

import com.extjs.gxt.ui.client.data.BeanModel;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.form.NumberField;
import com.extjs.gxt.ui.client.widget.form.TextField;
import com.extjs.gxt.ui.client.widget.grid.CellEditor;
import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
import com.extjs.gxt.ui.client.widget.grid.EditorGrid;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Random;
import com.gxtbindings.bindings.client.BeanModelConverter;
import com.gxtbindings.bindings.client.BeanModelStoreUtil;
import com.gxtbindings.bindings.client.ListStoreBinding;
import com.gxtbindings.bindings.client.util.EventList;

public class SimpleBindingDemo extends LayoutContainer {

	private EditorGrid<BeanModel> grid;
	
	private EventList<Person> list;
	
	private ListStoreBinding<Person,BeanModel> binding;
	
	public SimpleBindingDemo() {
		grid = new EditorGrid<BeanModel>(new ListStore<BeanModel>(), createColumnModel());
		grid.setAutoHeight(true);
		list = new EventList<Person>();
		
		binding = new ListStoreBinding<Person, BeanModel>(grid.getStore());
		binding.setConverter(new BeanModelConverter<Person>());
		binding.bind(list);
		
		add(grid);
		add(new Button("Load", new SelectionListener<ButtonEvent>() {
			public void componentSelected(ButtonEvent be) {
				load();
			}
		}));
		add(new Button("Add Person", new SelectionListener<ButtonEvent>() {
			public void componentSelected(ButtonEvent be) {
				addPerson();
			}
		}));
		add(new Button("Save", new SelectionListener<ButtonEvent>() {
			public void componentSelected(ButtonEvent be) {
				saveChanges();
			}
		}));
		add(new Button("Cancel", new SelectionListener<ButtonEvent>() {
			public void componentSelected(ButtonEvent be) {
				cancel();
			}
		}));
	}
	
	public void load()
	{
		list.clear();
		list.add(new Person("1", "John", "Smith", 20));
		list.add(new Person("2", "Paul", "Jones", 86));
		list.add(new Person("3", "Erica", "Adams", 23));
		list.add(new Person("4", "Sally", "Lee", 42));
		binding.commitChanges();
	}
	
	public void addPerson()
	{
		list.add(new Person("New", "Person", Random.nextInt(50)));
	}
	
	public void saveChanges()
	{
		List<Person> deletedPeople = binding.getRemovedObjects();
		List<Person> modifiedPeople = binding.getModifiedObjects();
		List<Person> newPeople = binding.getNewObjects();
		printList("Deleted", deletedPeople);
		printList("Modified", modifiedPeople);
		printList("New", newPeople);
		
		// Simulate save by updating local objects with ID's.
		for (Person p : list)
		{
			if (p.getId() == null)
			{
				p.setId(Random.nextInt(100) + "");
				grid.getStore().update(BeanModelStoreUtil.findModel(grid.getStore(), p));
			}
		}
		
		binding.commitChanges();
	}
	
	private void printList(String name, List<Person> p)
	{
		StringBuilder sb = new StringBuilder(name + " = {\n");
		for (Person person : p)
		{
			sb.append("{" + person.toString() + " },\n");
		}
		sb.append("}");
		GWT.log(sb.toString());
	}
	
	public void cancel()
	{
		binding.rejectChanges();
	}

	private static ColumnModel createColumnModel() {
		ColumnConfig[] cols = {
				new ColumnConfig("firstName", "First Name", 100),
				new ColumnConfig("lastName", "Last Name", 100),
				new ColumnConfig("age", "Age", 100),
		};
		cols[0].setEditor(new CellEditor(new TextField<String>()));
		cols[1].setEditor(new CellEditor(new TextField<String>()));
		cols[2].setEditor(new IntegerCellEditor());
		return new ColumnModel(Arrays.asList(cols));
	}
	
	public static class IntegerCellEditor extends CellEditor
	{
		public IntegerCellEditor() {
			super(new NumberField());
		}

		public Object postProcessValue(Object value) {
			if (value == null)
			{
				return null;
			}
			else
			{
				return ((Number)value).intValue();
			}
		}
		
		
	}
	
}
